package weka.groupminers;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import weka.core.Attribute;
import weka.core.Capabilities;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.OptionHandler;

public class ClusteringGroupMiner extends AbstractGroupMiner implements
		OptionHandler {

	/**
	 * 
	 */
	private static final long serialVersionUID = 5392984459934153096L;
	private Map<String, Integer> indexes;
	private String[] people;
	private List<GroupIteration> historial;
	private int[][] relations;
	private int[][] original;
	private int[] k;
	private StringBuilder results;
	private int index = 0;
	private GroupIteration iteration;
	private int MAX_USERS = 50;

	@Override
	public void mineGroups(Instances data) throws Exception {
		results = new StringBuilder();
		initializeMatrix(data);
		show();
		historial = new ArrayList<GroupIteration>();
		iteration = new GroupIteration(index);
		int maxRelation[] = new int[2];
		relations[2][3] = 150;
		relations[3][2] = 150;
		for (int i = 0; i < index - 1; i++) {
			showIteration();
			System.out.println("Iteration " + i + ":\n" + results.toString());
			maxRelation = this.findMaxRelation();
			// show();
			historial.add(iteration);
			iteration = iteration.uniteGroups(maxRelation[0], maxRelation[1],
					relations);
		}
	}

	private void showIteration() {
		for (Group g : iteration.getGroups()) {
			results.append("[");
			for (Integer i : g.getUsers()) {
				results.append(people[i] + ",");
			}
			results.append("] ");
		}
		results.append("Mod: " + iteration.getModularity(original, k, total()));
		results.append("\n");
	}

	private int total() {
		int total = 0;
		for (int i = 0; i < index; i++) {
			total += k[i];
		}
		return total;
	}

	private void show() {
		for (int i = 0; i < index; i++) {
			for (int j = 0; j < index; j++) {
				System.out.print("[" + relations[i][j] + "]");
			}
			System.out.println(".");
		}
	}

	private int[] findMaxRelation() {
		int[] max = new int[2];
		int maxValue = 0;
		for (int i = 0; i < index; i++) {
			for (int j = i + 1; j < index; j++) {
				if (relations[i][j] > maxValue) {
					maxValue = relations[i][j];
					max[0] = i;
					max[1] = j;
				}
			}
		}
		return max;
	}

	public void initializeMatrix(Instances data) {
		Instance instance;
		index = 0;
		int user2;
		String name;
		Attribute attr;
		indexes = new HashMap<String, Integer>();
		people = new String[MAX_USERS];
		for (int k = 0; k < data.numAttributes(); k++) {
			attr = data.attribute(k);
			for (int t = 0; t < attr.numValues(); t++) {
				name = attr.value(t);
				if (indexes.get(name) == null) {
					indexes.put(name, index);
					people[index] = name;
					this.index++;
				}
			}
		}
		relations = initialize(index);
		int user1;
		for (int i = 0; i < data.numInstances(); i++) {
			instance = data.instance(i);
			for (int j = 0; j < instance.numValues(); j++) {
				user1 = indexes.get(instance.stringValue(j));
				for (int s = j + 1; s < instance.numValues(); s++) {
					user2 = indexes.get(instance.stringValue(s));
					relations[user1][user2] += 1;
					relations[user2][user1] += 1;
					original[user1][user2] += 1;
					original[user2][user1] += 1;
				}
			}
		}
		k = new int[index];
		int sumatotal;
		for (int i = 0; i < index; i++) {
			sumatotal = 0;
			for (int j = 0; j < index; j++) {
				sumatotal += original[i][j];
			}
			k[i] = sumatotal;
		}
	}

	private int[][] initialize(int index2) {
		this.relations = new int[MAX_USERS][MAX_USERS];
		this.original = new int[MAX_USERS][MAX_USERS];
		for (int i = 0; i <= index2; i++) {
			for (int j = 0; j <= index2; j++) {
				relations[i][j] = 0;
				original[i][j] = 0;
			}
		}
		return relations;
	}

	@Override
	public Capabilities getCapabilities() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Enumeration listOptions() {
		return new Vector().elements();
	}

	@Override
	public void setOptions(String[] options) throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public String[] getOptions() {
		return new String[0];
	}

	@Override
	public String toString() {
		return results.toString();
	}

}
